package com.reservoir.log.aspect;

import cn.hutool.core.date.DateTime;
import com.reservoir.api.entity.SysOperLog;
import com.reservoir.log.annotation.Log;
import com.reservoir.log.enums.BusinessStatus;
import com.reservoir.log.service.AsyncLogService;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * 操作日志记录处理
 *
 * @author ruoyi
 */
@Aspect
@Component
@Slf4j
public class LogAspect {
    @Autowired
    private AsyncLogService asyncLogService;
    @Autowired
    private HttpServletRequest request;


    /**
     * 处理完请求后执行
     *
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut = "@annotation(controllerLog)")
    public void doAfterReturning(JoinPoint joinPoint, Log controllerLog) {
        handleLog(joinPoint, controllerLog, null);
    }

    /**
     * 拦截异常操作
     *
     * @param joinPoint 切点
     * @param e         异常
     */
    @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {
        handleLog(joinPoint, controllerLog, e);
    }

    protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e) {
        try {
            // *========数据库日志=========*//
            SysOperLog operLog = new SysOperLog();
            operLog.setOperIp(request.getRemoteAddr());
            operLog.setOperUrl(request.getRequestURI());
            operLog.setOperStatus(BusinessStatus.SUCCESS.ordinal());
            operLog.setOperTime(new DateTime());
            log.info("日志对象已加载");
            if (e != null) {
                operLog.setOperStatus(BusinessStatus.FAIL.ordinal());
                operLog.setErrorMsg(e.getMessage());
            }

            // 设置方法名称
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            operLog.setMethod(className + "." + methodName + "()");

            // 处理设置注解上的参数
            // 设置action动作
            operLog.setBusinessType(controllerLog.businessType().ordinal());
            // 设置标题
            operLog.setTitle(controllerLog.title());
            // 设置操作人类别
            operLog.setOperatorType(controllerLog.operatorType().ordinal());


            // 保存数据库
            asyncLogService.saveSysLog(operLog);
            log.info("插入成功");
        } catch (Exception exp) {
            // 记录本地异常日志
            log.error("==前置通知异常==");
            log.error("异常信息:{}", exp.getMessage());
            exp.printStackTrace();
        }
    }
}
